package design.patterns.structural;

/**
 * 代理模式
 * 解释：
 * 代理是一种结构型设计模式，
 * 让你能提供真实服务对象的替代品给客户端使用。
 * 代理接收客户端的请求并进行一些处理 （访问控制和缓存等）， 然后再将请求传递给服务对象。
 */

import java.util.HashMap;
import java.util.Map;

/**
 * 情景
 * （缓存服务器）
 * 用户 通过缓存服务器 进行访问服务
 * 如果缓存服务器中存在相同的访问，那么直接从缓存服务器返回，不需要再与后端服务器交互。
 *
 * 例子：
 * （将缓存服务器和后端服务器 看出一个整体，统称服务）
 * 1. 用户向服务发送请求 hi ，服务响应 你好      （用户 -> 缓存服务 -> 后端服务）
 * 2. 用户向服务再次发送请求 hi ，服务响应 你好    （用户 -> 缓存服务 ）
 *
 * 流程图如下：
 */

/*
```mermaid

graph LR

    User -->|发起请求| CacheServer

    CacheServer -- 存在缓存? -->|是| CacheServer -->|直接返回数据| User

    CacheServer -- 存在缓存? -->|否| BackendServer

    BackendServer -->|处理请求并响应| CacheServer

    CacheServer -->|缓存新数据并返回给用户| User
 */
public class G_Proxy {
    public static void main(String[] args) {
        BackendServer backendServer = new BackendServer();
        CacheBackendServer cacheBackendServer = new CacheBackendServer(backendServer);
        User user = new User(cacheBackendServer);

        System.out.println("第 一 次访问=====");
        user.sendUrl(UrlResponseMapperEnum.hi);

        System.out.println();

        System.out.println("第 二 次访问=====");
        user.sendUrl(UrlResponseMapperEnum.hi);

    }
}
interface Server{
    String ResponseData(UrlResponseMapperEnum urlResponseMapperEnum);
}
enum UrlResponseMapperEnum {
    hi("你好");
    private final String data;

    UrlResponseMapperEnum(String data) {
        this.data = data;
    }

    public String getData() {
        return data;
    }
}
class BackendServer implements Server{


    @Override
    public String ResponseData(UrlResponseMapperEnum urlResponseMapperEnum) {
        System.out.println("2.后端服务");
        return urlResponseMapperEnum.getData();
    }


}

class CacheBackendServer implements Server{
    private BackendServer backendServer;
    private Map<UrlResponseMapperEnum,String> cachedData = new HashMap<>();

    public CacheBackendServer(BackendServer backendServer) {
        this.backendServer = backendServer;
    }

    @Override
    public String ResponseData(UrlResponseMapperEnum urlResponseMapperEnum) {

        System.out.println("1.缓存服务");

        if (!cachedData.containsKey(urlResponseMapperEnum)){
            System.out.println("\t|--向后端发送请求");
            String responseData = backendServer.ResponseData(urlResponseMapperEnum);
            cachedData.put(urlResponseMapperEnum,responseData);
            return responseData;
        }
        System.out.println("1.1 有缓存，直接返回");
        return cachedData.get(urlResponseMapperEnum);
    }
}
class User{
    private Server server;

    public User(Server server) {
        this.server = server;
    }

    public void sendUrl(UrlResponseMapperEnum urlResponseMapperEnum){
        server.ResponseData(urlResponseMapperEnum);
    }
}
